 #include "mask.h"

//--------------------------------------------------------------------------------------------
Mask::Mask()
{
	this->resolution = 0;
	this->columns = 0;
	this->rows = 0;
}

//--------------------------------------------------------------------------------------------
Mask::Mask(float width, float height, int resolution)
{
	this->resolution = resolution;
	this->columns = (int) (width / resolution);
	this->rows = (int) (height / resolution);
	this->createPixelsBuffer(0);
}

//--------------------------------------------------------------------------------------------
Mask::Mask(Piece piece, int resolution)
{
	this->resolution = resolution;
	if (fmod(piece.width(), resolution) == 0)
		this->columns = (int) piece.width() / resolution;
	else
		this->columns = (int) piece.width() / resolution + 1;
	if (fmod(piece.height(), resolution) == 0)
		this->rows = (int) piece.height() / resolution;
	else
		this->rows = (int) piece.height() / resolution + 1;
	this->createPixelsBuffer(&piece);
}

//--------------------------------------------------------------------------------------------
Mask::~Mask()
{
}

//--------------------------------------------------------------------------------------------
int Mask::countColumns()
{
	return this->columns;
}

//--------------------------------------------------------------------------------------------
int Mask::countRows()
{
	return this->rows;
}

//--------------------------------------------------------------------------------------------
int Mask::getResolution()
{
	return this->resolution;
}

//--------------------------------------------------------------------------------------------
int Mask::width()
{
	return this->resolution * this->columns;
}

//--------------------------------------------------------------------------------------------
int Mask::height()
{
	return this->resolution * this->rows;
}

//--------------------------------------------------------------------------------------------
bool Mask::pixelValue(int row, int column)
{
	if ((this->rows > row) && (this->columns > column))
		return this->pixels.at((this->columns * row) + column);
	else
		return false;
}

//--------------------------------------------------------------------------------------------
bool Mask::overlap(Mask piece_mask, int starter_row, int starter_column)
{
	for (int i = 0; i < piece_mask.countRows(); i++)
		for (int j = 0; j < piece_mask.countColumns(); j++)
			if (this->pixelValue(i + starter_row, j + starter_column) && piece_mask.pixelValue(i, j))
				return true;
	return false;
}

//--------------------------------------------------------------------------------------------
void Mask::setPixelValue(int row, int column, bool value)
{
	if ((this->rows > row) && (this->columns > column))
		this->pixels.replace((this->columns * row) + column, value);
}

//--------------------------------------------------------------------------------------------
void Mask::combine(Mask piece_mask, int starter_row, int starter_column)
{
	for (int i = 0; i < piece_mask.countRows(); i++)
		for (int j = 0; j < piece_mask.countColumns(); j++)
			if (piece_mask.pixelValue(i,j))
				this->setPixelValue(i + starter_row, j + starter_column, true);
}

//---------------------------------------------------------------------------------------------
void Mask::descombine(Mask piece_mask,int starter_row,int starter_column)
{
	for (int i = 0; i < piece_mask.countRows(); i++)
		for (int j = 0; j < piece_mask.countColumns(); j++)
			if (piece_mask.pixelValue(i,j))
				this->setPixelValue(i + starter_row, j + starter_column, false);
}

//---------------------------------------------------------------------------------------------
void Mask::rotateMe()
{
	QVector<bool> aux = this->pixels;
	int new_rows = this->columns;
	this->columns = this->rows;
	this->rows = new_rows;
	int index = 0;
	for (int i = this->columns - 1; i >= 0; i--)
		for (int j = 0; j < this->rows; j++){
			this->setPixelValue(j, i, aux.at(index));
			index++;
	}
}

//----------------------------------------------------------------------------------------------
void Mask::reflectMe(int type)
{
	if (type == Vertical || type == VerticalHorizontal){
		int columns = (int) this->columns / 2;
		for (int i = 0; i < columns; i++)
			for (int j = 0; j < this->rows; j++){
				bool aux = this->pixelValue(j,i);
				this->setPixelValue(j, i, this->pixelValue(j, this->columns - i - 1));
				this->setPixelValue(j, this->columns - i - 1, aux);
			}
	}
	if (type == Horizontal || type == VerticalHorizontal){
		int rows = (int) this->rows / 2;
		for (int i = 0; i < this->columns; i++)
			for (int j = 0; j < rows; j++){
				bool aux = this->pixelValue(j,i);
				this->setPixelValue(j, i, this->pixelValue(this->rows - j - 1, i));
				this->setPixelValue(this->rows - j - 1, i, aux);
			}
	}
}

//----------------------------------------------------------------------------------------------
void Mask::draw(QPainter *painter, bool distinguishCells)
{
	painter->setPen(QPen(QColor(255,170,0,100), 0.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
	for (int i = 0; i < this->rows; i++)
		for (int j = 0; j < this->columns; j++){
			QPolygon cell(QRect(QPoint(j * this->resolution, i * this->resolution), QPoint((j+1) * this->resolution, (i+1) * this->resolution)));
			if (distinguishCells)
				if (this->pixelValue(i, j))
					painter->setBrush(QBrush(QColor(255,170,0,90), Qt::SolidPattern));
				else
					painter->setBrush(QBrush(QColor(250,250,187,50), Qt::SolidPattern));
			else
				painter->setBrush(QBrush(QColor(250,250,187,50), Qt::SolidPattern));
			painter->drawPolygon(cell);
		}
}

//--------------------------------------------------------------------------------------------
int Mask::freePixels(){
	int count = 0;
	for (int i = 0; i < this->countRows(); i++)
		for (int j = 0; j < this->countColumns(); j++)
			if (this->pixelValue(i,j) == false)
				count++;
	return count;
}

//--------------------------------------------------------------------------------------------
void Mask::createPixelsBuffer(Piece *piece)
{
	this->pixels = QVector<bool>(this->columns * this->rows, false);
	if (piece){
		QPolygonF polygon(piece->getVertexes().toVector());
		for (int i = 0; i < this->rows; i++)
			for (int j = 0; j < this->columns; j++){
				QPolygonF cell(QRectF(QPointF(j * this->resolution, i * this->resolution), QPointF((j+1) * this->resolution, (i+1) * this->resolution))); 
				if (!polygon.intersected(cell).empty())
					this->setPixelValue(i, j, true);
			}
	}
}
